﻿var actionDelay = 1000; // delay between click actions

function process(taskListGeneratorObject, parentTask, doneCallback) {
    /// <summary>
    /// 
    /// </summary>
    /// <param name="taskListGeneratorObject">
    /// generator: function that generates task list
    /// params: list of parameters to pass to generator function
    /// </param>
    /// <param name="doneCallback"></param>
    var taskList = taskListGeneratorObject.Generator.call(this, parentTask);
    processTaskList(0, taskList, taskListGeneratorObject).done(doneCallback);
}

function processTaskList(index, list, taskListGeneratorObject) {
    /// <summary>
    /// 
    /// </summary>
    /// <param name="index"></param>
    /// <param name="list"></param>
    /// <returns type=""> deferred object </returns>
    if (index >= list.length) {
        var deferred = new $.Deferred();
        deferred.resolve();
        return deferred;
    }

    return processSingleTask(list.get(index), taskListGeneratorObject.ActionOnItem, taskListGeneratorObject.Next).then(function () {
        return processTaskList(++index, list, taskListGeneratorObject);
    });
}

function processSingleTask(item, actionOnItem, nextTaskListGeneratorObject) {
    /// <summary>
    /// 
    /// </summary>
    /// <param name="item"></param>
    /// <param name="actionOnItem"></param>
    /// <returns type=""> deferred object </returns>
    var deferred = new $.Deferred();

    setTimeout(function () {
        actionOnItem(item);

        if (nextTaskListGeneratorObject !== undefined && nextTaskListGeneratorObject !== null) {
            setTimeout(function (parentItem) {
                process(nextTaskListGeneratorObject, parentItem, function () {
                    deferred.resolve();
                });
            }, actionDelay, item);
        }
        else {
            deferred.resolve();
        }
    }, actionDelay);

    return deferred;
}